/*
 * $Id: ContactTests.m 249 2008-09-09 13:58:25Z jon $
 * Sleeper
 *
 * Created by Jon Gordon on 5/24/08
 * Copyright Jon Gordon.  All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#import "ContactTests.h"

#import "CallsignTests.h"

#import "QEArrlData.h"
#import "QEContact.h"



@implementation ContactTests
- (void)testContactInitialization
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
     STAssertEqualObjects([contact serialSent], serialSent, @"serialSent property of contact does not equal initialization value");
     STAssertEqualObjects([contact time], time, @"time property of contact does not equal initialization value");
     STAssertEqualObjects([contact freq], frequency, @"frequency property of contact does not equal initialization value");
     STAssertEqualObjects([contact call], callsign, @"callsign property of contact does not equal initialization value");
     STAssertEqualObjects([contact serialRcvd], serialRcvd, @"serialRcvd property of contact does not equal initialization value");
     STAssertEqualObjects([contact prec], precedence, @"precedence property of contact does not equal initialization value");
     STAssertEqualObjects([contact check], check, @"check property of contact does not equal initialization value");
     STAssertEqualObjects([contact section], section, @"section property of contact does not equal initialization value");
    
     [contact release];
} // testContactInitialization


- (void)testContactSerialSentValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSNumber *serialSentTest = serialSent;
     STAssertTrue([contact validateSerialSent:&serialSentTest error:nil],
		  @"failed to recognize %@ as a valid sent serial number",
		  serialSent);
     STAssertTrue((serialSent == serialSentTest),
		  @"validation routine improperly replaced source number with new object");
    
     id serialSentString = [serialSent stringValue];
     BOOL result = [contact validateSerialSent:&serialSentString error:nil];
     STAssertTrue(result,
		  @"failed to recognize \"%@\" as valid string representation of a sent serial #",
		  [serialSent stringValue]);
     if (result) {
	  STAssertEqualObjects(serialSentString, serialSent,
			       @"validation routine improperly converted string representing %@ to %@",
			       serialSent,
			       serialSentString);
     } // if
    
     NSString *serialSentSrc = @"boogers";
     serialSentString = serialSentSrc;
     result = [contact validateSerialSent:&serialSentString error:nil];
     STAssertFalse(result,
		   @"validation routine improperly converted \"%@\" to value %@",
		   serialSentSrc,
		   serialSentString);
    
     [contact release];
} // testContactSerialSentValidation


- (void)testContactFrequencyValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSNumber *frequencyTest = frequency;
     STAssertTrue([contact validateFreq:&frequencyTest error:nil],
		  @"failed to recognize %@ as a valid frequency",
		  frequencyTest);
     STAssertTrue((frequency == frequencyTest),
		  @"validation routine improperly replaced frequency with new object");
    
     id frequencyString = [frequency stringValue];
     BOOL result = [contact validateFreq:&frequencyString error:nil];
     STAssertTrue(result,
		  @"failed to recognize \"%@\" as valid string representation of a frequency",
		  [frequency stringValue]);
     if (result) {
	  STAssertEqualObjects(frequencyString, frequency,
			       @"validation routine improperly converted string representing %@ to %@",
			       frequency,
			       frequencyString);
     } // if
    
     NSString *frequencySrc = @"boogers";
     frequencyString = frequencySrc;
     result = [contact validateFreq:&frequencyString error:nil];
     STAssertFalse(result,
		   @"frequency validation routine improperly converted \"%@\" to value %@",
		   frequencySrc,
		   frequencyString);
    
     [contact release];
} // testContactFrequencyValidation


- (void)testContactCallsignValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSArray *validCallsigns = listValidCallsigns();
     NSEnumerator *enumerator = [validCallsigns objectEnumerator];
     while (callsign = [enumerator nextObject]) {
	  STAssertTrue([contact validateCall:&callsign error:nil], @"failed to recognize \'%@\' as valid callsign", callsign);
     } // while
} // testContactCallsignValidation


- (void)testContactSerialRcvdValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSNumber *serialRcvdTest = serialRcvd;
     STAssertTrue([contact validateSerialRcvd:&serialRcvdTest error:nil],
		  @"failed to recognize %@ as a valid received serial number",
		  serialRcvd);
     STAssertTrue((serialRcvd == serialRcvdTest),
		  @"validation routine improperly replaced source number with new object");
    
     id serialRcvdString = [serialRcvd stringValue];
     BOOL result = [contact validateSerialRcvd:&serialRcvdString error:nil];
     STAssertTrue(result,
		  @"failed to recognize \"%@\" as valid string representation of a received serial #",
		  [serialRcvd stringValue]);
     if (result) {
	  STAssertEqualObjects(serialRcvdString, serialRcvd,
			       @"validation routine improperly converted string representing %@ to %@",
			       serialRcvd,
			       serialRcvdString);
     } // if
    
     NSString *serialRcvdSrc = @"boogers";
     serialRcvdString = serialRcvdSrc;
     result = [contact validateSerialRcvd:&serialRcvdString error:nil];
     STAssertFalse(result,
		   @"validation routine improperly converted \"%@\" to value %@",
		   serialRcvdSrc,
		   serialRcvdString);
    
     [contact release];
} // testContactSerialRcvdValidation


- (void)testContactPrecedenceValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSString *prSrc = nil;
     STAssertTrue([contact validatePrec:&prSrc error:nil],
		  @"incorrectly rejected nil precedence");
    
     prSrc = @"";
     STAssertTrue([contact validatePrec:&prSrc error:nil],
		  @"incorrectly rejected blank precedence");
    
     NSArray *validPrecedences = [NSArray arrayWithObjects:@"Q", @"q", @"A", @"a", @"B", @"b",
					  @"U", @"u", @"M", @"m", @"S", @"s", nil];
     NSEnumerator *srcEnum = [validPrecedences objectEnumerator];
     NSString *prTest, *prExpect;
     while (nil != (prSrc = [srcEnum nextObject])) {
	  prTest = prSrc;
	  prExpect = [prSrc uppercaseString];
	  STAssertTrue([contact validatePrec:&prTest error:nil], 
		       @"incorrectly rejected valid precedence \"%@\"--returned precedence \"%@\"",
		       prSrc, prTest);
	  if ([prSrc isEqual:prExpect]) {
	       STAssertEquals(prSrc, prTest, 
			      @"incorrectly replaced source object \"%@\" with new object \"%@\"",
			      prSrc, prTest);
	  } else {
	       STAssertFalse((prSrc == prTest),
			     @"incorrectly failed to replace source object \"%@\" with new object",
			     prSrc);
	       STAssertTrue([prExpect isEqual:prTest],
			    @"incorrectly replaced source \"%@\" with \"%@\"; expected \"%@\"",
			    prSrc, prTest, prExpect);
	  } // else
     } // while
    
     NSArray *badPrecedences = [NSArray arrayWithObjects:@"foobity", @"4", @"\"",
					@"Aa", @"aA", @"QQ", nil];
     srcEnum = [badPrecedences objectEnumerator];
     while (nil != (prSrc = [srcEnum nextObject])) {
	  prTest = prSrc;
	  STAssertFalse([contact validatePrec:&prTest error:nil], 
			@"incorrectly accepted bad precedence \"%@\"--returned precedence \"%@\"",
			prSrc, prTest);
	  STAssertTrue((prSrc == prTest),
		       @"incorrectly replaced source object \"%@\" with new object \"%@\"",
		       prSrc, prTest);
     } // while
    
     [contact release];
} // testContactPrecedenceValidation


- (void)testCheckValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSNumber *ckSrc = nil;
     STAssertTrue([contact validateCheck:&ckSrc error:nil],
		  @"incorrectly rejected nil check");
    
     NSArray *goodChecks = [NSArray arrayWithObjects:
					 [NSNumber numberWithInt:0],
				    [NSNumber numberWithInt:1],
				    [NSNumber numberWithInt:98],
				    [NSNumber numberWithInt:99],
				    [NSNumber numberWithFloat:0.0],
				    [NSNumber numberWithFloat:1.0],
				    [NSNumber numberWithFloat:98.0],
				    [NSNumber numberWithFloat:99.0],
				    nil];
    
     NSEnumerator *srcEnum = [goodChecks objectEnumerator];
     NSNumber *ckTest, *ckExpect;
     while (nil != (ckSrc = [srcEnum nextObject])) {
	  ckTest = ckSrc;
	  ckExpect = [NSNumber numberWithInt:[ckSrc intValue]];
	  STAssertTrue([contact validateCheck:&ckTest error:nil], 
		       @"incorrectly rejected valid check %@--returned check %@",
		       ckSrc, ckTest);
	  STAssertEquals(ckSrc, ckTest, 
			 @"incorrectly replaced source object with value %@ with new object with value %@",
			 ckSrc, ckTest);
     } // while
    
     [contact release];
} // testCheckValidation


- (void)testSectionValidation
{
     NSNumber *serialSent = [NSNumber numberWithInt:123];
     NSDate   *time       = [[[NSDate alloc] init] autorelease];
     NSNumber *frequency  = [NSNumber numberWithFloat:7175.0];
     NSString *callsign   = @"KA3LUD";
     NSNumber *serialRcvd = [NSNumber numberWithInt:42];
     NSString *precedence = @"A";
     NSNumber *check      = [NSNumber numberWithInt:83];
     NSString *section    = @"EPA";
    
     QEContact *contact = [[QEContact alloc] initWithSerialSent:serialSent 
					     time:time
					     freq:frequency 
					     call:callsign 
					     serialRcvd:serialRcvd 
					     prec:precedence 
					     check:check 
					     section:section];
    
     STAssertNotNil(contact, @"failed to allocate or initialize instance of QEContact");
    
     NSEnumerator *sectionsEnum = [[[[[[QEArrlData init] alloc] autorelease] allSections] valueForKeyPath:@"@distinctUnionOfObjects.sectionAbbr"] objectEnumerator];
     NSString *sectionAbbr;
     NSString *testSectionAbbr;
     while (nil != (sectionAbbr = [sectionsEnum nextObject])) {
	  NSLog(@"    validating section \"%@\"", sectionAbbr);
	  testSectionAbbr = sectionAbbr;
	  STAssertTrue([contact validateSection:&testSectionAbbr error:nil],
		       @"failed to accept valid section \"%@\"",
		       sectionAbbr);
	  STAssertEquals(sectionAbbr, testSectionAbbr,
			 @"incorrectly replaced valid section \"%@\" with \"%@\"",
			 sectionAbbr,
			 testSectionAbbr);
     } // while
    
     sectionsEnum = [[[[[[QEArrlData init] alloc] autorelease] allSections] valueForKeyPath:@"@distinctUnionOfObjects.sectionAbbr"] objectEnumerator];
     while (nil != (sectionAbbr = [sectionsEnum nextObject])) {
	  sectionAbbr = [sectionAbbr lowercaseString];
	  NSLog(@"    validating section \"%@\"", sectionAbbr);
	  testSectionAbbr = sectionAbbr;
	  STAssertTrue([contact validateSection:&testSectionAbbr error:nil],
		       @"failed to accept valid section \"%@\"",
		       sectionAbbr);
	  STAssertFalse((testSectionAbbr == sectionAbbr),
			@"incorrectly failed to correct section \"%@\" to \"%@\"",
			sectionAbbr, [sectionAbbr uppercaseString]);
	  STAssertEqualObjects([sectionAbbr uppercaseString], testSectionAbbr,
			       @"incorrectly changed section \"%@\" to \"%@\"",
			       sectionAbbr,
			       testSectionAbbr);
     } // while
    
     sectionsEnum = [[NSArray arrayWithObjects:@".", @"*", @"TX", @"tx", @"NA", @"US", @"CA", nil] objectEnumerator];
     while (nil != (sectionAbbr = [sectionsEnum nextObject])) {
	  NSLog(@"    validating section \"%@\"", sectionAbbr);
	  testSectionAbbr = sectionAbbr;
	  STAssertFalse([contact validateSection:&testSectionAbbr error:nil],
			@"incorrectly accepted invalid section \"%@\"",
			sectionAbbr);
	  STAssertTrue((testSectionAbbr == sectionAbbr),
		       @"incorrectly changed section \"%@\" to \"%@\"",
		       sectionAbbr, [sectionAbbr uppercaseString]);
     } // while    
    
     [contact release];
} // testSectionValidation
@end

